from django.conf import settings
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponse, HttpResponseRedirect
from django.template import RequestContext
from django.shortcuts import render_to_response, get_object_or_404
from models import Category, Dish, Review, Photo, ProfilePhoto, Place, UserProfile
from forms import DishForm, DishReviewForm
from urls import consts as urlconsts

#from utils.json_functions import json_encode
from utils.serialization_helpers import serialize_dishes

def urls_consts_processor(request):
    return { 'urls' : urlconsts }

def home(request):
    category_count_tuple = [(cat, len(cat.dishes.all())) for cat in Category.objects.all()]
    reviews = Review.objects.order_by('-id')[:10]
    
    # get all dish photos
    photos = Photo.objects.filter(content_type__app_label='food', content_type__model='dish')
    
    variables = RequestContext(request, { "categories" : category_count_tuple, 'reviews' : reviews, 'photos' : photos })
    
    return render_to_response('food/main.html', variables)

def dish_location_map(dish):
    ''' Returns the string to display for location, and the location url '''
    
    return (dish, dish.place.get_display_name(), dish.place.slug)

def category(request, slug):
    cat = get_object_or_404(Category, slug=slug)
    dishes = cat.dishes.all()
    dish_location_tuple = map(dish_location_map, dishes)
    json = serialize_dishes(dishes)
    print str(json)
    variables = RequestContext(request, { 
        "category" : cat,
        "dish_location_tuple" : dish_location_tuple,
        "dishes_json" : json
    })
    return render_to_response('food/category.html', variables)

def dish(request, slug):
    dish = get_object_or_404(Dish, slug=slug)
    reviews_by_user = None

    # figure out if user has reviewed this dish before
    if request.user.is_authenticated():
        # get all revies of this dish by user
        reviews_by_user = Review.objects.filter(profile__user__username__iexact=request.user.username,
                                                dish__slug__iexact=slug).order_by('-date_added')
                
#    if request.method == 'POST':
        
        # check if user is logged in
        # add upload image functionality from dish page
        
#        uploadImageForm = UploadImageForm(request.POST, request.FILES)

#        if uploadImageForm.is_valid():
#            img = uploadImageForm.cleaned_data['img']
#            p = Photo(content_object=dish, original_image=img, profile=request.user.get_profile())
#            p.save()
#            return HttpResponseRedirect("/d/" + slug)
#    else:
#        uploadImageForm = UploadImageForm()
        
    variables = RequestContext(request, { "dish" : dish, "reviews_by_user" : reviews_by_user })
    return render_to_response('food/dish.html', variables)

def place(request, slug):
    place = get_object_or_404(Place, slug=slug)
    dishes = place.dish_set.all()
    variables = RequestContext(request, { "place" : place, "dishes" : dishes})
    return render_to_response('food/place.html', variables)


@login_required
def add_review(request, id):
    ''' add a review for a dish '''
    
    dish = get_object_or_404(Dish, id=id)
    if request.method == 'POST':
        form = DishReviewForm(request.POST, request.FILES)
        if form.is_valid():
            # create new review and save
            review = Review()
            review.rating = form.cleaned_data['rating']
            review.text = form.cleaned_data['text']
            review.dish = dish
            review.profile = request.user.get_profile()
            
            review.save()
            
            # save photo
            try:
                if form.cleaned_data.has_key('img'):
                    img = form.cleaned_data['img']
                    if img:
                        p = Photo(content_object=review.dish, original_image=img, user=request.user)
                        p.save()
            except Exception as e:
                raise Exception("Exception saving photo in add_review: " + str(e))               
            
            return HttpResponseRedirect('/' + urlconsts['PROFILE'] + '/' + request.user.username)
    else:        
        form = DishReviewForm()
            
    variables = { 
        'form' : form,
        'dish' : dish 
    }            
    rc = RequestContext(request, variables)
    return render_to_response('food/add_review.html', rc)

@login_required
def edit_review(request, id):
    ''' edit an existing review '''
    
    review = get_object_or_404(Review, id=id)
    if request.method == 'POST':
        form = DishReviewForm(request.POST, request.FILES)
        if form.is_valid():
            # update the existing review and save
            review.rating = form.cleaned_data['rating']
            review.text = form.cleaned_data['text']
            review.save()
            
            # save photo
            try:
                if form.cleaned_data.has_key('img'):
                    img = form.cleaned_data['img']
                    if img:
                        p = Photo(content_object=review.dish, original_image=img, user=request.user)
                        p.save()
            except Exception as e:
                raise Exception("Exception saving photo in edit_review: " + str(e))                
            
            return HttpResponseRedirect('/' + urlconsts['PROFILE'] + '/' + request.user.username)
    else:        
        form = DishReviewForm()
            
    variables = { 
        'form' : form, 
        'review' : review
    }            
    rc = RequestContext(request, variables)
    return render_to_response('food/edit_review.html', rc)

def display_review(request, username, dishname):
    pass

def profile(request, username):
    user = get_object_or_404(User, username=username)
    dishes_liked = Dish.objects.filter(users_voted_good__username__iexact=username)
    dishes_disliked = Dish.objects.filter(users_voted_bad__username__iexact=username)

    # get all user's dish photos
    photos = Photo.objects.filter(content_type__app_label='food', content_type__model='dish', user__username=username)
    
    is_owner = False
    if request.user.is_authenticated() and request.user.username.lower() == username.lower():
        is_owner = True
        
    variables = RequestContext(request, {
         'profile' : user.get_profile(),
         'is_owner' : is_owner,
         'dishes_liked' : dishes_liked, 
         'dishes_disliked' : dishes_disliked,
         'dish_photos' : photos
     })
    return render_to_response('food/profile.html', variables)

@login_required
def delete_photo(request, id):
    photo = get_object_or_404(Photo, id=id)
    photo.delete()
    return HttpResponseRedirect('/' + urlconsts['PROFILE'] + '/' + request.user.username)

def add_dish(request):
    variables = RequestContext(request, { "form" : DishForm() })
    return render_to_response('food/add_dish.html', variables)

@login_required
def rate(request, rating, id):
    dish = get_object_or_404(Dish, id=id)
    r = rating.lower()
    existingReview = Review.objects.filter(profile=request.user.get_profile(), dish=dish)
    if existingReview:
        existingReview = existingReview[0]
        existingReviewText = existingReview.text
    
    if request.method == 'POST':
        form = DishReviewForm(request.POST, request.FILES)
        if form.is_valid():
            # create new review and save
            reviewText = form.cleaned_data['text']
            
            if existingReview:
                existingReview.text = reviewText
                existingReview.save()
            else:
                review = Review()
                review.dish = dish
                review.profile = request.user.get_profile()
                review.text = reviewText
                review.save()
            
            print request.FILES
            
            # save photo
            try:
                if form.cleaned_data.has_key('img'):
                    img = form.cleaned_data['img']
                    if img:
                        p = Photo(content_object=dish, original_image=img, user=request.user)
                        p.save()
            except:
                raise Exception("doh")               
            
            return HttpResponseRedirect('/' + request.user.username)
    # if GET, then test if user has reviewed the specific dish,
    # if he has, then populate fields with the existing review info
    # if not, then create new form
    else:
        user_voted_good = dish.users_voted_good.filter(username=request.user.username)
        user_voted_bad = dish.users_voted_bad.filter(username=request.user.username)

        if r == 'good':
            if user_voted_good:
                pass
            elif user_voted_bad:
                dish.users_voted_bad.remove(request.user)
                dish.users_voted_good.add(request.user)
            else:
                dish.users_voted_good.add(request.user)
        elif r == 'bad':
            if user_voted_bad:
                pass
            elif user_voted_good:
                dish.users_voted_good.remove(request.user)
                dish.users_voted_bad.add(request.user)
            else:
                dish.users_voted_bad.add(request.user)
        else:
            raise Exception("doh")
    
        dish.save()
        
        form = DishReviewForm()
        if existingReview:
            pass
            # display all images that user has uploaded for this dish
            # and with ability to delete
            
    variables = { 
        "dish" : dish,
        "rating" : r,
        "form" : form
    }
            
    if existingReview:
        variables['reviewText'] = existingReview.text
        
    rc = RequestContext(request, variables)
    return render_to_response('food/rate.html', rc)

def register(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            new_user = form.save()
            new_user = authenticate(username=new_user.username, password=form.cleaned_data["password1"])
            login(request, new_user)
            return HttpResponseRedirect('/' + urlconsts['PROFILE'] + '/' + request.user.username)
    else:
        form = UserCreationForm()
    variables = RequestContext(request, { "form": form })
    return render_to_response("registration/register.html", variables)